以下是讀完 Clean code 第三章節(part 2)的筆記:
public class UserValidator {
  private Cryptographer cryptographer;
  public boolean checkPassword(String userName, String password) {
    User user = UserGateway.findByName(userName);
    if (user != User.NULL) {
      String codedPhrase = user.getPhraseEncodedByPassword();
      String phrase = cryptographer.decrypt(codedPhrase, password);
      if ("Valid Password".equals(phrase)) {
        Session.initialize();
        return true;
      }
    }
    return false;
  }
}
函數就兩種功能
因此不要混和這兩種功能
看看這個函數
使用情境
如果重構成setAndCheckIfExists, 仍對if的可讀性沒提高
最好是這樣重構, command與query分離
if(attributeExists("username"))
{
	setAttribute("username", "unclebob");
}
從command函數回傳錯誤碼, 是一種破壞CQS原則
比如if(deletePage(page) == E_OK), 是一種簡單的情境
但如果更深的nest
if (deletePage(page) == E_OK) {
  if (registry.deleteReference(page.name) == E_OK) {
    if (configKeys.deleteKey(page.name.makeKey()) == E_OK) {
      logger.log("page deleted");
    } else {
      logger.log("configKey not deleted");
    }
  } else {
    logger.log("deleteReference from registry failed");
  }
} else {
  logger.log("delete failed");
  return E_ERROR;
}
這樣是強迫呼叫者都得立刻處理錯誤碼
透過拋出exception, 簡化錯誤處理
try 
{
	deletePage(page);
	registry.deleteReference(page.name);
	configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e)
{
	logger.log(e.getMessage());
}
public void delete(Page page) {
  try {
    deletePageAndAllReferences(page);
  } catch (Exception e) {
    logError(e);
  }
}
private void deletePageAndAllReferences(Page page) throws Exception {
  deletePage(page);
  registry.deleteReference(page.name);
  configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e) {
  logger.log(e.getMessage());
}
public enum Error {
	OK,
	INVALID,
	NO_SUCH,LOCKED,
	OUT_OF_RESOURCES,
	WAITING_FOR_EVENT;
}